package com.xjuse.yida.commom.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.UnknownHostException;
import java.util.UUID;

/**
 * @Description: 网络工具包
 * @Date: 2020/8/21 8:40
 * @Author: 1
 */
@Slf4j
public class NetworkUtils {

    private static final String[] PROXY_REMOTE_IP_ADDRESS =
            {"X-Real-IP", "x-forwarded-for", "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR"};

    public static final String UNKNOWN_STRING = "UNKNOWN";

    /**
     * 获取IP地址
     * <p>
     * 使用Nginx等反向代理软件， 则不能通过request.getRemoteAddr()获取IP地址
     * 如果使用了多级反向代理的话，X-Forwarded-For的值并不止一个，而是一串IP地址，X-Forwarded-For中第一个非unknown的有效IP字符串，则为真实IP地址
     */
    public static String getIpAddr(HttpServletRequest request) {
        for (String headerKey : PROXY_REMOTE_IP_ADDRESS) {
            String header = request.getHeader(headerKey);
            if (null != header && !"".equals(header) && !UNKNOWN_STRING.equalsIgnoreCase(header)) {
                String[] strings = header.split(",");
                for (String string : strings) {
                    String value = string.trim();
                    if (null != value && !"".equals(value) && !UNKNOWN_STRING.equalsIgnoreCase(value)) {
                        return value;
                    }
                }
            }
        }

        return request.getRemoteAddr().trim();
    }

    /**
     * 获取机器唯一标识
     * <p>优先获取网卡物理地址，如果获取不到则生成uuid
     *
     * @return
     * @throws Exception
     */
    public static String uniqueMachine() throws Exception {
        InetAddress inetAddress = InetAddress.getLocalHost();

        String macAddress = getMacAddress(inetAddress);

        if (null == macAddress || "".equals(macAddress.trim())) {
            macAddress = UUID.randomUUID().toString().replaceAll("-", "");
        }

        return macAddress;
    }

    /**
     * 获取网卡物理地址
     *
     * @param ia
     * @return
     * @throws Exception
     */
    public static String getMacAddress(InetAddress ia) throws Exception {
        StringBuffer sb = new StringBuffer();

        try {
            //获得网络接口对象（即网卡），并得到mac地址，mac地址存在于一个byte数组中。
            byte[] mac = NetworkInterface.getByInetAddress(ia).getHardwareAddress();

            for (int i = 0; i < mac.length; i++) {
                if (i != 0) {
                    sb.append("-");
                }

                // mac[i] & 0xFF 把byte转化为正整数
                String s = Integer.toHexString(mac[i] & 0xFF);
                sb.append(s.length() == 1 ? 0 + s : s);
            }
        } catch (Exception e) {
            log.error("obtain mac address error", e.getMessage());
        }

        return sb.toString().toUpperCase();
    }

    /**
     * 获取主机名
     * @return
     */
    public static String getHostname() {
        InetAddress inetAddress = null;
        try {
            inetAddress = InetAddress.getLocalHost();
        } catch (UnknownHostException e) {
            log.error("Obtain hostname error", e);
        }

        if (null == inetAddress) {
            return null;
        }

        return inetAddress.getHostName();
    }

    /**
     * <p>获取本地IP</p>
     * @return
     */
    public static String getLocalIp() {
        InetAddress inetAddress = null;
        try {
            inetAddress = InetAddress.getLocalHost();
        } catch (UnknownHostException e) {
            log.error("Obtain hostname error", e);
        }

        if (null == inetAddress) {
            return null;
        }

        return inetAddress.getHostAddress();
    }

    /**
     * byte数组转换成16进制字符串
     *
     * @param src
     * @return
     */
    public static String bytesToHexString(byte[] src) {
        StringBuilder stringBuilder = new StringBuilder();
        if (src == null || src.length <= 0) {
            return null;
        }
        for (int i = 0; i < src.length; i++) {
            int v = src[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }


    /**
     * 获取IP地址及端口
     *
     * @param socketaddress
     * @return {ip}:{prot}  字符串
     */
    public static String getIpAndProt(InetSocketAddress socketaddress) {
        String address = "";

        if (null != socketaddress) {
            address = getIp(socketaddress) + ":" + socketaddress.getPort();
        }

        return address;
    }

    /**
     * 获取IP地址
     *
     * @param socketaddress
     * @return {ip} 字符串
     */
    public static String getIp(InetSocketAddress socketaddress) {
        String ip = "";
        if (socketaddress != null) {
            InetAddress address = socketaddress.getAddress();
            ip = (address == null) ? socketaddress.getHostName() : address.getHostAddress();
        }
        return ip;
    }
}
